package com.wmx.rocketmq.helloFriend;

import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;

/**
 * 事务消息监听器，
 * 使用了 rocketMQTemplate.sendMessageInTransaction 时，则必须提供此监听器，否则启动失败
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2020/12/13 16:13
 */
@RocketMQTransactionListener
public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
    /**
     * 执行本地事务
     * 1、无论 rocketMQTemplate.sendMessageInTransaction 所处的业务代码是否发生异常，只有消息发送成功都会进入此方法
     * 2、这里返回 commit 时，则 MQ 服务器将之前发送的半消息标记为可以让消费者消费，从而消费者可以接收
     * 3、这里返回 ROLLBACK 时，则 MQ 服务器将之前发送的半消息丢弃，从而消费者不会接收到
     * 4、这里返回 UNKNOWN 时，则 MQ 服务器将进行事务回查，1分钟后会进入到下面的 checkLocalTransaction 再次确认
     *
     * @param msg
     * @param arg
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
            System.out.println("执行本地事务");
            //调用其它 Service 业务层业务代码
            //业务执行成功，提交消息
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            //业务执行失败，记录日志，回滚消息
            e.printStackTrace();
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    /**
     * 当上面 executeLocalTransaction 方法没有明确返回 提交或者回滚时，MQ 服务器会延时后进入此方法进行再次确认
     * 当 MQ Server发现消息长时间处于半消息状态时,将向消息生产者发送请求,询问该消息的最终状态(提交或回滚，进入此方法
     *
     * @param msg
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        System.out.println("回查本地事务");
        return RocketMQLocalTransactionState.ROLLBACK;
    }
}